package com.bcbim.smart_water.pipeManagement.service;


import com.bcbim.common.util.LngLonUtil;
import com.bcbim.smart_water.pipeManagement.mapper.PipeManagementMapper;
import com.bcbim.smart_water.road.mapper.RoadMapper;
import com.bcbim.smart_water_interface.line.VO.PipelineVO;
import com.bcbim.smart_water_interface.pipeManagement.dto.AddLineInSetDTO;
import com.bcbim.smart_water_interface.pipeManagement.dto.AddPointSetDTO;
import com.bcbim.smart_water_interface.pipeManagement.dto.PipelineFrameSelectInput;
import com.bcbim.smart_water_interface.pipeManagement.service.PipeManagementService;
import com.bcbim.smart_water_interface.pipeManagement.vo.*;
import com.bcbim.smart_water_interface.pipeline.VO.PipelineLineModelListVO;
import com.bcbim.smart_water_interface.pipeline.VO.PipelinePointModelListVO;
import com.bcbim.smart_water_interface.point.VO.PipePointVO;
import com.bcbim.smart_water_interface.road.vo.RoadPullVO;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.dubbo.config.annotation.Service;
import org.gavaghan.geodesy.Ellipsoid;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: 管网管理service实现类
 * @Author haoshuai
 * @Date 2021/8/19
 * @Version V1.0
 **/
@Service(timeout = 60 * 1000, group = "pipeManagement", version = "1.0.0")
public class PipeManagementServiceImpl implements PipeManagementService {

    @Autowired
    private PipeManagementMapper pipeManagementMapper;
    @Autowired
    private RoadMapper roadMapper;

    /**
     * @Description: 查询管线列表不含分页
     * @Param: code 管线编号(模糊检索)
     * @Param: roadId 道路id
     * @Param: uses 用途码值
     * @Param: pipeDiameterMin 管径范围(最小)
     * @Param: pipeDiameterMax 管径范围(最大)
     * @Param: buryType 埋设方式
     * @Param: material 材质
     * @Return: List<listLineVO>
     * @Author: haoshuai
     * @Date: 2021/8/19
     */
    @Override
    public List<PipeListVO> listLineNoPaging(AddLineInSetDTO params) {
        return pipeManagementMapper.listLineNoPaging(params);
    }

    /**
     * 查询管点列表不含分页
     *
     * @param params 前端传入管点加入选集参数
     * @param: roadId 道路id
     * @param: uses 用途
     * @param: feature 特征
     * @param: attachmen 附属
     * @param: startBury 开始井底深
     * @param: endBury 结束井底深
     * @param: startHigh 起始高程
     * @param: endHigh 结束高程
     * @return: com.bcbim.common.response.vo.ReturnPageMsg
     * @author wxc
     * @date 2021/8/25  11:11
     */
    @Override
    public List<PipeListVO> pointNoPaging(AddPointSetDTO params) {
        return pipeManagementMapper.pointNoPaging(params);
    }

    /**
     * 获取道路下拉列表
     *
     * @return com.bcbim.common.response.vo.ReturnMsg
     * @author wxc
     * @date 2021/8/13  11:25
     */
    @Override
    public List<RoadPullVO> getRoadPull() {
        return roadMapper.getRoadPull();
    }

    @Override
    public Map<String, Object> getAllPipeList() {
        HashMap<String, Object> map = new HashMap<>(2);
//        查找全部管点
        List<PipelinePointModelListVO> pointList = pipeManagementMapper.getAllPoint();
//        查找全部管线
        List<PipelineLineModelListVO> lineList = pipeManagementMapper.getAllLine();
        map.put("pointList", pointList);
        map.put("lineList", lineList);
        return map;
    }

    /***
     * 查询存放到redis中的管点数据列表（未分页）
     *
     * @param params 查询参数
     * @param: roadId 道路id
     * @param: uses 用途
     * @param: feature 特征
     * @param: attachmen 附属
     * @param: startBury 开始井底深
     * @param: endBury 结束井底深
     * @param: startHigh 起始高程
     * @param: endHigh 结束高程
     * @return java.util.List<com.bcbim.pipeline_interface.pipeManagement.vo.PipePointListVO>
     * @author wxc
     * @date 2021/8/30  10:43
     */
    @Override
    public List<PipePointListVO> listPointNoLimit(AddPointSetDTO params) {
        return pipeManagementMapper.listPointNoLimit(params);
    }

    /**
     * 查询存放到redis中的管线数据列表（未分页）
     *
     * @param params 查询参数
     * @Param: code 管线编号(模糊检索)
     * @Param: roadId 道路id
     * @Param: uses 用途码值
     * @Param: pipeDiameterMin 管径范围(最小)
     * @Param: pipeDiameterMax 管径范围(最大)
     * @Param: buryType 埋设方式
     * @Param: material 材质
     * @Return: List<PipeLineListVO>
     * @Author: wxc
     * @Date: 2021/8/30
     */
    @Override
    public List<PipeLineListVO> listLineNoLimit(AddLineInSetDTO params) {
        return pipeManagementMapper.listLineNoLimit(params);
    }

    /**
     * 通过管线id集合查询数据,用于显示水波流向
     *
     * @param lineIdList 集选管线id集合
     * @return java.util.List<com.bcbim.pipeline_interface.pipeManagement.vo.PipeLineListUseWaterVO>
     * @author wxc
     * @date 2021/9/2  16:39
     */
    @Override
    public List<PipeLineListUseWaterVO> listPipeLineUseWater(List<String> lineIdList) {
        return pipeManagementMapper.listPipeLineUseWater(lineIdList);
    }

    /**
     * 通过框选位置添加管点集选
     *
     * @param pipelineFrameSelectInput 框选位置
     * @return java.util.List<com.bcbim.pipeline_interface.pipeManagement.vo.PipeListVO>
     * @author wxc
     * @date 2021/10/11
     */
    @Override
    public List<PipeListVO> listPointByCodes(PipelineFrameSelectInput pipelineFrameSelectInput) {
        return pipeManagementMapper.listPointByCodes(pipelineFrameSelectInput);
    }

    /**
     * 通过框选位置添加管线集选
     *
     * @param pipelineFrameSelectInput 框选位置
     * @return java.util.List<com.bcbim.pipeline_interface.pipeManagement.vo.PipeListVO>
     * @author wxc
     * @date 2021/10/11
     */
    @Override
    public List<PipeListVO> listLineByCodes(PipelineFrameSelectInput pipelineFrameSelectInput) {
        return pipeManagementMapper.listLineByCodes(pipelineFrameSelectInput);
    }

    @Override
    public List<PipeLinePointsListVO> listPipelinePoints(String[] pointIds) {
        List<PipelineVO> pipelineVOList = pipeManagementMapper.listPipelineByPointIds(pointIds);
        if (ObjectUtils.isEmpty(pipelineVOList)) {
            return null;
        }
        List<PipePointVO> pipePointVOList = pipeManagementMapper.listPipePointByPointIds(pointIds);
        List<PipeLinePointsListVO> linePointsListVOS = new ArrayList<>();
        double position = 0;
        String startPointId = getStartPointId(pipelineVOList);
        for (int j = 0; j < pipePointVOList.size(); j++) {
            PipePointVO pipePointVO = pipePointVOList.get(j);
            if (pipePointVO.getId().equals(startPointId)) {
                PipeLinePointsListVO pointsListVO = new PipeLinePointsListVO();
                pointsListVO.setCode(pipePointVO.getCode())
                        .setHigh(pipePointVO.getHigh())
                        .setUses(pipePointVO.getUses())
                        .setPosition(position);
                linePointsListVOS.add(pointsListVO);
                break;
            }
        }
        for (int i = 0; i < pipelineVOList.size(); i++) {
            PipelineVO pipelineVO = pipelineVOList.get(i);
            double distance = LngLonUtil.getDistanceMeter(Double.parseDouble(pipelineVO.getStartLat()), Double.parseDouble(pipelineVO.getStartLon()),
                    Double.parseDouble(pipelineVO.getEndLat()), Double.parseDouble(pipelineVO.getEndLon()), Ellipsoid.WGS84);
            if (pipelineVO.getStartPointId().equals(startPointId)) {
                PipeLinePointsListVO lineListVO = new PipeLinePointsListVO();
                lineListVO.setCode(pipelineVO.getCode())
                        .setUses(pipelineVO.getUses())
                        .setStartHigh(pipelineVO.getStartHigh())
                        .setEndHigh(pipelineVO.getEndHigh())
                        .setLength(BigDecimal.valueOf(distance))
                        .setPipeDiameter(pipelineVO.getPipeDiameter());
                linePointsListVOS.add(lineListVO);
                position += distance;

                for (int m = 0; m < pipePointVOList.size(); m++) {
                    PipePointVO pipePointVO = pipePointVOList.get(m);
                    if (pipelineVO.getEndPointId().equals(pipePointVO.getId())) {
                        PipeLinePointsListVO pointsListVO = new PipeLinePointsListVO();
                        pointsListVO.setCode(pipePointVO.getCode())
                                .setHigh(pipePointVO.getHigh())
                                .setUses(pipePointVO.getUses())
                                .setPosition(position);
                        linePointsListVOS.add(pointsListVO);
                        startPointId = pipePointVO.getId();
                        i = 0;
                        break;
                    }

                }
            }
        }
        if (linePointsListVOS.size() < pipelineVOList.size() + pipePointVOList.size()) {
            return null;
        }
        return linePointsListVOS;
    }

    public static final double WIDTH = 0.7;
    public static final double X = 1;

    @Override
    public Map<String, Object> listPipelinePointsByPointIds(String[] pointIds) {
        List<PipelineVO> pipelineVOList = pipeManagementMapper.listPipelineByPointIds(pointIds);
        if (ObjectUtils.isEmpty(pipelineVOList)) {
            return null;
        }
        List<PipePointVO> pipePointVOList = pipeManagementMapper.listPipePointByPointIds(pointIds);
        int size = pipelineVOList.size() + pipePointVOList.size();
        List<PipeLinePointChartVO> linePointsListVOS = new ArrayList<>();
        List<PipeCoordinateVO> pipeCoordinateUp = new ArrayList<>();
        List<PipeCoordinateVO> pipeCoordinateDown = new ArrayList<>();
        String startPointId = getStartPointId(pipelineVOList);
        double x = 0;
        for (int j = 0; j < pipePointVOList.size(); j++) {
            PipePointVO pipePointVO = pipePointVOList.get(j);
            if (pipePointVO.getId().equals(startPointId)) {
                PipeLinePointChartVO pointChartVO = new PipeLinePointChartVO();
                pointChartVO.setCode(pipePointVO.getCode())
                        .setUses(pipePointVO.getUses());
                linePointsListVOS.add(pointChartVO);
                double x1 = X + WIDTH;
                double y1 = pipePointVO.getHigh().doubleValue() - pipePointVO.getBury().doubleValue();
                x = x1;
                PipeCoordinateVO p1 = new PipeCoordinateVO();
                PipeCoordinateVO p2 = new PipeCoordinateVO();
                PipeCoordinateVO p3 = new PipeCoordinateVO();
                PipeCoordinateVO p4 = new PipeCoordinateVO();
                p1.setX(X).setY(pipePointVO.getHigh().doubleValue());
                p2.setX(X).setY(y1);
                p3.setX(x1).setY(pipePointVO.getHigh().doubleValue());
                p4.setX(x1).setY(y1);

                pipeCoordinateUp.add(p1);
                pipeCoordinateUp.add(p3);
                pipeCoordinateDown.add(p2);
                pipeCoordinateDown.add(p4);
                break;
            }
        }

        int i = 0;
        double diameter = 0;
        while (i < pipePointVOList.size()) {
            for (int p = 0; p < pipelineVOList.size(); p++) {
                PipelineVO pipelineVO = pipelineVOList.get(p);
                double distance = LngLonUtil.getDistanceMeter(Double.parseDouble(pipelineVO.getStartLat()), Double.parseDouble(pipelineVO.getStartLon()),
                        Double.parseDouble(pipelineVO.getEndLat()), Double.parseDouble(pipelineVO.getEndLon()), Ellipsoid.WGS84);
                if (pipelineVO.getStartPointId().equals(startPointId)) {
                    PipeLinePointChartVO lineChart = new PipeLinePointChartVO();
                    lineChart.setCode(pipelineVO.getCode())
                            .setUses(pipelineVO.getUses());
                    linePointsListVOS.add(lineChart);
                    PipeCoordinateVO l1 = new PipeCoordinateVO();
                    PipeCoordinateVO l2 = new PipeCoordinateVO();
                    PipeCoordinateVO l3 = new PipeCoordinateVO();
                    PipeCoordinateVO l4 = new PipeCoordinateVO();
                    diameter = pipelineVO.getPipeDiameter();
                    double y1 = pipelineVO.getStartHigh().doubleValue() - pipelineVO.getStartBury().doubleValue();
                    double y2 = y1 + diameter;
                    double y3 = pipelineVO.getEndHigh().doubleValue() - pipelineVO.getEndBury().doubleValue();
                    double y4 = y3 + diameter;
                    l1.setX(x).setY(y1);
                    l2.setX(x).setY(y2);
                    x = x + distance;
                    l3.setX(x).setY(y3);
                    l4.setX(x).setY(y4);
                    pipeCoordinateDown.add(l1);
                    pipeCoordinateDown.add(l3);
                    pipeCoordinateUp.add(l2);
                    pipeCoordinateUp.add(l4);

                    for (int m = 0; m < pipePointVOList.size(); m++) {
                        PipePointVO pipePointVO = pipePointVOList.get(m);
                        if (pipelineVO.getEndPointId().equals(pipePointVO.getId())) {
                            PipeLinePointChartVO pointChart = new PipeLinePointChartVO();
                            pointChart.setCode(pipePointVO.getCode())
                                    .setUses(pipePointVO.getUses());
                            linePointsListVOS.add(pointChart);
                            startPointId = pipePointVO.getId();
                            PipeCoordinateVO p1 = new PipeCoordinateVO();
                            PipeCoordinateVO p2 = new PipeCoordinateVO();
                            PipeCoordinateVO p3 = new PipeCoordinateVO();
                            PipeCoordinateVO p4 = new PipeCoordinateVO();

                            double y = pipePointVO.getHigh().doubleValue() - pipePointVO.getBury().doubleValue();
                            p1.setX(x).setY(pipePointVO.getHigh().doubleValue());
                            p2.setX(x).setY(y);
                            x = x + WIDTH;
                            p3.setX(x).setY(pipePointVO.getHigh().doubleValue());
                            p4.setX(x).setY(y);

                            pipeCoordinateUp.add(p1);
                            pipeCoordinateUp.add(p3);
                            pipeCoordinateDown.add(p2);
                            pipeCoordinateDown.add(p4);
                            break;
                        }
                    }
                    pipelineVOList.remove(p);
                    break;
                }
                if (pipelineVO.getEndPointId().equals(startPointId)) {
                    PipeLinePointChartVO lineChart = new PipeLinePointChartVO();
                    lineChart.setCode(pipelineVO.getCode())
                            .setUses(pipelineVO.getUses());
                    linePointsListVOS.add(lineChart);
                    PipeCoordinateVO l1 = new PipeCoordinateVO();
                    PipeCoordinateVO l2 = new PipeCoordinateVO();
                    PipeCoordinateVO l3 = new PipeCoordinateVO();
                    PipeCoordinateVO l4 = new PipeCoordinateVO();
                    diameter = pipelineVO.getPipeDiameter();
                    double y1 = pipelineVO.getStartHigh().doubleValue() - pipelineVO.getStartBury().doubleValue();
                    double y2 = y1 + diameter;
                    double y3 = pipelineVO.getEndHigh().doubleValue() - pipelineVO.getEndBury().doubleValue();
                    double y4 = y3 + diameter;
                    l1.setX(x).setY(y3);
                    l2.setX(x).setY(y4);
                    x = x + distance;
                    l3.setX(x).setY(y1);
                    l4.setX(x).setY(y2);
                    pipeCoordinateDown.add(l1);
                    pipeCoordinateDown.add(l3);
                    pipeCoordinateUp.add(l2);
                    pipeCoordinateUp.add(l4);

                    for (int m = 0; m < pipePointVOList.size(); m++) {
                        PipePointVO pipePointVO = pipePointVOList.get(m);
                        if (pipelineVO.getStartPointId().equals(pipePointVO.getId())) {
                            PipeLinePointChartVO pointChart = new PipeLinePointChartVO();
                            pointChart.setCode(pipePointVO.getCode())
                                    .setUses(pipePointVO.getUses());
                            linePointsListVOS.add(pointChart);
                            startPointId = pipePointVO.getId();
                            PipeCoordinateVO p1 = new PipeCoordinateVO();
                            PipeCoordinateVO p2 = new PipeCoordinateVO();
                            PipeCoordinateVO p3 = new PipeCoordinateVO();
                            PipeCoordinateVO p4 = new PipeCoordinateVO();

                            double y = pipePointVO.getHigh().doubleValue() - pipePointVO.getBury().doubleValue();
                            p1.setX(x).setY(pipePointVO.getHigh().doubleValue());
                            p2.setX(x).setY(y);
                            x = x + WIDTH;
                            p3.setX(x).setY(pipePointVO.getHigh().doubleValue());
                            p4.setX(x).setY(y);

                            pipeCoordinateUp.add(p1);
                            pipeCoordinateUp.add(p3);
                            pipeCoordinateDown.add(p2);
                            pipeCoordinateDown.add(p4);
                            break;
                        }
                    }
                    pipelineVOList.remove(p);
                    break;
                }
            }
            i++;
        }
        Map<String, Object> map = new HashMap<>();
        map.put("pipeLinePoint", linePointsListVOS);
        pipeCoordinateUp.add(0, pipeCoordinateDown.get(0));
        pipeCoordinateUp.add(pipeCoordinateDown.get(pipeCoordinateDown.size() - 1));
        map.put("upCoordinate", pipeCoordinateUp);
        map.put("downCoordinate", pipeCoordinateDown);
        if (linePointsListVOS.size() < size) {
            return null;
        }
        return map;
    }

    public String getStartPointId(List<PipelineVO> pipelineVOList) {
        String startPointId = pipelineVOList.get(0).getStartPointId();
        for (int i = 1; i < pipelineVOList.size(); i++) {
            if (pipelineVOList.get(i).getEndPointId().equals(startPointId)) {
                startPointId = pipelineVOList.get(i).getStartPointId();
                continue;
            }
            if (pipelineVOList.get(i).getStartPointId().equals(startPointId)){
                startPointId = pipelineVOList.get(i).getEndPointId();
                continue;
            }
        }
        return startPointId;
    }
}
